package middleware

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"go-micro.dev/v4/util/log"
	"go.uber.org/zap"
	"maya-service/config"
	"maya-service/constant"
	"maya-service/lib/authentication"
	"maya-service/model"
	"maya-service/store/redis"
	"maya-service/utils/request"
	"net/http"
	"strings"
)

func Auth() gin.HandlerFunc {
	return func(c *gin.Context) {
		// web操作直接下去
		os := c.GetHeader("source")
		if os == "web" {
			// token 认证
			token := c.GetHeader("Authorization")
			parts := strings.SplitN(token, " ", 2)
			if !(len(parts) == 2 && parts[0] == "Bearer") {
				c.JSON(http.StatusUnauthorized, nil)
				c.Abort()
				return
			}

			if opts, err := authentication.Extract(parts[1]); err != nil {
				c.JSON(http.StatusUnauthorized, nil)
				c.Abort()
				return
			} else {
				// 判断token是否过期
				result, _err := redis.KV.Get(c.Request.Context(), fmt.Sprintf("admin_token:%v", opts.UserID)).Result()
				if _err != nil || result == "" {
					c.JSON(http.StatusUnauthorized, nil)
					c.Abort()
					return
				}

				userData, err := redis.KV.Get(c.Request.Context(), fmt.Sprintf("userData:%v", opts.UserID)).Result()
				if err != nil {
					log.Error("web 鉴权失败", zap.Any("userId", opts.UserID))
					c.JSON(http.StatusUnauthorized, nil)
					c.Abort()
					return
				}

				userInfo := &model.SysUsersInfo{}
				err = json.Unmarshal([]byte(userData), userInfo)
				if err != nil {
					log.Error("web 鉴权失败 json unmarshal", zap.Any("userId", opts.UserID))
					c.JSON(http.StatusUnauthorized, nil)
					c.Abort()
					return
				}

				ctx := context.WithValue(c.Request.Context(), constant.UserData, &request.UserData{
					UserName:  userInfo.Username,
					AvatarUrl: userInfo.HeaderImg,
					Unionid:   opts.UserID,
				})
				ctx = context.WithValue(ctx, constant.UserId, opts.UserID)
				c.Request = c.Request.WithContext(ctx)
			}
			c.Next()
			return
		}

		// 商城
		//用户登录终端来源：2、H5(包括微信内部浏览器)；3、Android；4、IOS；6、微信小程序；7、百度小程序；8、支付宝小程序；9、抖音小程序
		tSource := c.GetHeader("Terminal-source")
		if tSource == "6" {
			// token 认证
			token := c.GetHeader("Authorization")
			if token == "" {
				c.JSON(http.StatusUnauthorized, nil)
				c.Abort()
				return
			}

			userData, err := request.GetUserMemberInfo(token, config.Conf.Env)
			if err != nil {
				fmt.Println("GetUserMemberInfo token:", token, "err:", err)
				c.JSON(http.StatusUnauthorized, nil)
				c.Abort()
				return
			}

			if userData == nil || userData.Unionid == "" {
				c.JSON(http.StatusUnauthorized, nil)
				c.Abort()
				return
			}

			ctx := context.WithValue(c.Request.Context(), constant.UserData, userData)
			ctx = context.WithValue(ctx, constant.UserId, userData.Unionid)
			c.Request = c.Request.WithContext(ctx)

			c.Next()
			return
		}

		// 鉴权过程
		if os == "h5" {
			token := c.GetHeader("Authorization")
			if token == "" && config.Conf.Env == "prod" {
				c.JSON(http.StatusUnauthorized, nil)
				c.Abort()
				return
			}

			if token != "" {
				userData, err := request.GetUserDataByToken(token, config.Conf.Env, "")
				if err != nil {
					fmt.Println("GetUserDataByToken token:", token, "err:", err)
					c.JSON(http.StatusUnauthorized, nil)
					c.Abort()
					return
				}

				if userData == nil || userData.Unionid == "" {
					c.JSON(401, gin.H{
						"code": 500,
						"data": nil,
						"msg":  "token expired",
					})
					c.Abort()
					return
				}

				ctx := context.WithValue(c.Request.Context(), constant.UserData, userData)
				ctx = context.WithValue(ctx, constant.UserId, userData.Unionid)
				c.Request = c.Request.WithContext(ctx)
			}

			c.Next()
			return
		}

		// 鉴权过程
		token := c.GetHeader("Authorization")
		if token == "" && config.Conf.Env == "prod" {
			c.JSON(http.StatusUnauthorized, nil)
			c.Abort()
			return
		}

		if token != "" {
			storeData, err := request.GetStoreInfo(token, config.Conf.Env)
			if err != nil {
				fmt.Println("GetUserDataByToken token:", token, "err:", err)
				c.JSON(http.StatusUnauthorized, nil)
				c.Abort()
				return
			}

			if storeData.StoreID == 0 {
				c.JSON(401, gin.H{
					"code": 500,
					"data": nil,
					"msg":  "token expired",
				})
				c.Abort()
				return
			}

			ctx := context.WithValue(c.Request.Context(), constant.UserData, storeData)
			ctx = context.WithValue(ctx, constant.UserId, storeData.StoreID)
			c.Request = c.Request.WithContext(ctx)
		}

		c.Next()

	}
}
